package com.oolatina.views;

import java.io.File;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.drawable.AnimationDrawable;
import android.graphics.drawable.Drawable;
import android.media.ThumbnailUtils;
import android.net.Uri;
import android.os.AsyncTask;
import android.provider.MediaStore;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.widget.ImageView;
import android.widget.ImageView.ScaleType;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;

import com.androidquery.AQuery;
import com.androidquery.callback.AjaxStatus;
import com.androidquery.callback.BitmapAjaxCallback;
import com.androidquery.callback.ImageOptions;
import com.oolatina.R;

public class RemoteImageView extends RelativeLayout {

	public static final int DEFAULT_ERROR_DRAWABLE_RES_ID = android.R.drawable.ic_dialog_alert;

	private static final String ATTR_AUTO_LOAD = "autoLoad";
	private static final String ATTR_IMAGE_URL = "imageUrl";
	private static final String ATTR_ERROR_DRAWABLE = "errorDrawable";

	private static final int STATE_DEFAULT = 0;
	private static final int STATE_LOADED = 1;
	private static final int STATE_LOADING = 2;

	private int state = STATE_DEFAULT;
	private String imageUrl;
	private boolean autoLoad;

	private View progressViewContainer;
	private Drawable progressDrawable, errorDrawable;

	private RemoteImageViewListener listener;
	private ImageView imageView;

	private AQuery aq;
	public ImageOptions aqOptions = new ImageOptions();

	protected int cornerRadius;

	private boolean showPreloader;

	private String localImagePath;

	/**
	 * Use this method to inject an image loader that will be shared across all
	 * instances of this class. If the shared reference is null, a new
	 * {@link RemoteImageLoader} will be instantiated for every instance of this
	 * class.
	 * 
	 * @param imageLoader
	 *            the shared image loader
	 * 
	 *            public static void setSharedImageLoader(RemoteImageLoader
	 *            imageLoader) { sharedImageLoader = imageLoader; }
	 */

	/**
	 * @param context
	 *            the view's current context
	 * @param imageUrl
	 *            the URL of the image to download and show
	 * @param autoLoad
	 *            Whether the download should start immediately after creating
	 *            the view. If set to false, use {@link #loadImage()} to
	 *            manually trigger the image download.
	 */
	public RemoteImageView(Context context, int srcDrawableId,
			String imageUrl, boolean autoLoad) {
		super(context);
		initialize(context, imageUrl, null, null, autoLoad, null);
	}

	/**
	 * @param context
	 *            the view's current context
	 * @param imageUrl
	 *            the URL of the image to download and show
	 * @param progressDrawable
	 *            the drawable to be used for the {@link ProgressBar} which is
	 *            displayed while the image is loading
	 * @param errorDrawable
	 *            the drawable to be used if a download error occurs
	 * @param autoLoad
	 *            Whether the download should start immediately after creating
	 *            the view. If set to false, use {@link #loadImage()} to
	 *            manually trigger the image download.
	 */
	public RemoteImageView(Context context, int srcDrawableId,
			String imageUrl, Drawable progressDrawable, Drawable errorDrawable,
			boolean autoLoad) {
		super(context);
		if (!isInEditMode()) {
			initialize(context, imageUrl, progressDrawable, errorDrawable,
					autoLoad, null);
		}
	}

	public RemoteImageView(Context context, AttributeSet attributes) {
		super(context, attributes);

		// Read all Android specific view attributes into a typed array first.
		if (!isInEditMode()) {
			initialize(context, imageUrl, progressDrawable, errorDrawable,
					autoLoad, attributes);
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see android.widget.RelativeLayout#onLayout(boolean, int, int, int, int)
	 */
	@Override
	protected void onLayout(boolean changed, int l, int t, int r, int b) {
		// TODO Auto-generated method stub
		super.onLayout(changed, l, t, r, b);

	}

	private void initialize(Context context, String imageUrl,
			Drawable progressDrawable, Drawable errorDrawable,
			boolean autoLoad, AttributeSet attributes) {
		isInEditMode();
		aq = new AQuery(context);
		aqOptions = new ImageOptions();
		aqOptions.memCache = true;
		aqOptions.fileCache = true;
		this.imageUrl = imageUrl;
		this.autoLoad = autoLoad;
		this.progressDrawable = progressDrawable;
		this.errorDrawable = errorDrawable;

		setGravity(Gravity.CENTER);
		imageView = new ImageView(getContext(), attributes) {
			@Override	
			protected void onDraw(Canvas canvas) {
				if (!onMaskCanvas(canvas)) {
					super.onDraw(canvas);
				}
			}
		};
		RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(
				RelativeLayout.LayoutParams.FILL_PARENT,
				RelativeLayout.LayoutParams.FILL_PARENT);
		lp.addRule(CENTER_IN_PARENT);
		imageView.setLayoutParams(lp);

		addView(imageView);
		// progressViewContainer = new RelativeLayout(getContext());
		progressViewContainer = buildProgressSpinnerView(getContext());
		addView(progressViewContainer);

		if (autoLoad) {
			loadImage();
		} else {
			showProgressView(false);
		}
	}

	protected View buildProgressSpinnerView(Context context) {
		ProgressBar loadingSpinner = new ProgressBar(context);
		loadingSpinner.setIndeterminate(true);
		if (this.progressDrawable == null) {
			this.progressDrawable = loadingSpinner.getIndeterminateDrawable();
		} else {
			loadingSpinner.setIndeterminateDrawable(progressDrawable);
			if (progressDrawable instanceof AnimationDrawable) {
				((AnimationDrawable) progressDrawable).start();
			}
		}

		RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(
				progressDrawable.getIntrinsicWidth(),
				progressDrawable.getIntrinsicHeight());
		lp.addRule(CENTER_IN_PARENT);
		loadingSpinner.setLayoutParams(lp);

		return loadingSpinner;
	}

	/**
	 * Use this method to trigger the image download if you had previously set
	 * autoLoad to false.
	 */
	public void loadImage() {
		reset();
		if (state != STATE_LOADING) {
			if (imageUrl == null) {
				Log.e(VIEW_LOG_TAG,
						"image URL is null; did you forget to set it for this view?");
				return;
				// throw new
				// IllegalStateException("image URL is null; did you forget to set it for this view?");
			}
			if (!imageUrl.equals("")) {
				Log.i(VIEW_LOG_TAG, imageUrl);
				showProgressView(true);
				// aq.id(imageView).progress(progressViewContainer).image(imageUrl,aqOptions);

				// create a bitmap ajax callback object
				BitmapAjaxCallback cb = new BitmapAjaxCallback() {
					protected void callback(String url, ImageView iv,
							Bitmap bm,
							com.androidquery.callback.AjaxStatus status) {
						if (bm != null){
							iv.setImageBitmap(bm);
							
						}
						onImageLoaded(url, iv, bm, status);
					};
				};
				
				// configure the callback
				cb.url(imageUrl);
				cb.fileCache(true);
				cb.memCache(true);
				if (cornerRadius > 0)
					cb.round(cornerRadius);
				
				cb.animation(AQuery.FADE_IN);
				cb.ratio(1.0f);

				// invoke it with an image view
				aq.id(imageView).image(cb);
				//aq.id(imageView).image(imageUrl, true, true, 0, 0, null, AQuery.FADE_IN);
				//aq.id(imageView).image(imageUrl,true,true,0,0,null,AQuery.FADE_IN,1.0f);

				// aq.id(imageView).progress(progressViewContainer).image(imageUrl,true,false);
				// imageLoader.loadImage(imageUrl, imageView, new
				// DefaultImageLoaderHandler(this));
			}
		}
	}

	/**
	 * @param url
	 * @param iv
	 * @param bm
	 * @param status
	 */
	protected void onImageLoaded(String url, ImageView iv, Bitmap bm,
			AjaxStatus status) {
		progressViewContainer.setVisibility(View.GONE);
		imageView.setVisibility(View.VISIBLE);

		imageView.measure(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
		imageView.requestLayout();
		//this.setBackgroundResource(getResources().getColor(R.color.transparent));
		if (listener != null)
			listener.onImageLoaded(this, bm);

	}

	public boolean isLoaded() {
		return state == STATE_LOADED;
	}

	public void setImageUrl(String imageUrl) {
		this.imageUrl = imageUrl;
	}

	/**
	 * Often you have resources which usually have an image, but some don't. For
	 * these cases, use this method to supply a placeholder drawable which will
	 * be loaded instead of a web image.
	 * 
	 * @param imageResourceId
	 *            the resource of the placeholder image drawable
	 */
	public void setNoImageDrawable(int imageResourceId) {
		imageView.setImageDrawable(getContext().getResources().getDrawable(
				imageResourceId));
		showProgressView(false);
	}

	/**
	 * Reset to view to its initial state, i.e. hide the progress item and show
	 * the image.
	 */
	public void reset() {
		showProgressView(false);
		if (imageView.getDrawable() != null) {
			imageView.getDrawable().setCallback(null);
		}
		Bitmap bmp = imageView.getDrawingCache();
		if (bmp != null) {
			bmp.recycle();
			bmp = null;
		}
		imageView.setImageDrawable(null);
		imageView.setImageBitmap(null);

	}

	private void showProgressView(boolean show) {
		if (show) {
			state = STATE_LOADING;
			// progressViewContainer.setVisibility(View.VISIBLE);
			// imageView.setVisibility(View.INVISIBLE);
		} else {
			state = STATE_DEFAULT;
			// progressViewContainer.setVisibility(View.INVISIBLE);
			// imageView.setVisibility(View.VISIBLE);
		}
	}

	/**
	 * Returns the URL of the image to show. Corresponds to the view attribute
	 * ignition:imageUrl.
	 * 
	 * @return the image URL
	 */
	public String getImageUrl() {
		return imageUrl;
	}

	/**
	 * Whether or not the image should be downloaded immediately after view
	 * inflation. Corresponds to the view attribute ignition:autoLoad (default:
	 * true).
	 * 
	 * @return true if auto downloading of the image is enabled
	 */
	public boolean isAutoLoad() {
		return autoLoad;
	}

	/**
	 * The drawable that should be used to indicate progress while downloading
	 * the image. Corresponds to the view attribute
	 * android:indeterminateDrawable. If left blank, the platform's standard
	 * indeterminate progress drawable will be used.
	 * 
	 * @return the progress drawable
	 */
	public Drawable getProgressDrawable() {
		return progressDrawable;
	}

	/**
	 * The drawable that will be shown when the image download fails.
	 * Corresponds to the view attribute ignition:errorDrawable. If left blank,
	 * a stock alert icon from the Android platform will be used.
	 * 
	 * @return the error drawable
	 */
	public Drawable getErrorDrawable() {
		return errorDrawable;
	}

	/**
	 * The progress view that is shown while the image is loaded.
	 * 
	 * @return the progress view, default is a {@link ProgressBar}
	 */
	public View getProgressView() {
		return progressViewContainer;
	}

	public static interface RemoteImageViewListener {
		public void onImageLoaded(RemoteImageView remoteImageView, Bitmap bm);
	}

	/**
	 * Use this method to set a listener for events raised by the remote image
	 * view such as image loaded.
	 * 
	 * @param listener
	 *            an implementation of the {@link RemoteImageViewListener}
	 *            interface
	 */
	public void setRemoteImageViewListener(RemoteImageViewListener listener) {
		this.listener = listener;
	}

	public ImageView getImageView() {
		return imageView;
	}

	public void setImageView(ImageView imageView) {
		this.imageView = imageView;
	}

	public boolean onMaskCanvas(Canvas canvas) {
		return false;
	}

	/**
	 * @param imageUrl
	 */
	public void loadImmediate(String imageUrl, boolean showLoader) {
		// progressViewContainer.setVisibility(showLoader?View.VISIBLE:View.GONE);
		loadImmediate(imageUrl);
	}

	/**
	 * @param imageUrl
	 */
	public void loadImmediate(String imageUrl) {
		// Log.i(VIEW_LOG_TAG, imageUrl);
		setImageUrl(imageUrl);
		if (imageUrl != null && imageUrl.trim().length() > 0)
			loadImage();
	}

	public void hideLoader() {
		progressViewContainer.setVisibility(View.GONE);
		imageView.setVisibility(View.VISIBLE);
	}

	public void showLoader() {
		progressViewContainer.setVisibility(View.VISIBLE);
	}

	public void disableLoader() {
		showPreloader = false;
		progressViewContainer.setVisibility(View.GONE);
		imageView.setVisibility(View.VISIBLE);
	}

	public void setScaleType(ScaleType scaletype) {
		imageView.setScaleType(scaletype);
	}

	public void setImageURI(Uri uri) {
		imageView.setImageURI(uri);
	}

	public void setImageResource(int resId) {
		imageView.setImageResource(resId);
	}

	/**
	 * @param thumb
	 */
	public void setThumbBitmap(Bitmap thumb) {
		imageView.setImageBitmap(thumb);
	}

	/**
	 * @param path
	 */
	public void loadLocalImage(String imagePath) {
		reset();
		if (state != STATE_LOADING) {
			if (imagePath == null) {
				Log.e(VIEW_LOG_TAG,
						"image URL is null; did you forget to set it for this view?");
				return;
				// throw new
				// IllegalStateException("image URL is null; did you forget to set it for this view?");
			}
			if (!imagePath.equals("")) {
				showProgressView(false);

				File file = new File(imagePath);

				// load image from file with callback
				aq.id(imageView).image(file, false,
						imageView.getMeasuredWidth(), new BitmapAjaxCallback() {

					@Override
					public void callback(String url, ImageView iv,
							Bitmap bm, AjaxStatus status) {

						iv.setImageBitmap(bm);

						// do something with the bm

					}

				});
				/*
				 * 
				 * //
				 * aq.id(imageView).progress(progressViewContainer).image(imagePath
				 * ,aqOptions);
				 * 
				 * // create a bitmap ajax callback object BitmapAjaxCallback cb
				 * = new BitmapAjaxCallback() { protected void callback(String
				 * url, ImageView iv, Bitmap bm,
				 * com.androidquery.callback.AjaxStatus status) {
				 * onImageLoaded(url, iv, bm, status); }; };
				 * 
				 * // configure the callback
				 * cb.url(imagePath).animation(AQuery.FADE_IN).ratio(1.0f);
				 * cb.fileCache(true); cb.memCache(true); if (cornerRadius > 0)
				 * cb.round(cornerRadius);
				 * 
				 * // invoke it with an image view aq.id(imageView).image(cb);
				 * 
				 * //
				 * aq.id(imageView).progress(progressViewContainer).image(imageUrl
				 * ,true,false); // imageLoader.loadImage(imageUrl, imageView,
				 * new // DefaultImageLoaderHandler(this));
				 */
			}
		}
	}

	/**
	 * Method to load the Video thumbnail and set it to the imageview
	 * 
	 * @param path
	 */
	public void loadLocalVideoImage(String path) {
		showProgressView(true);
		showLoader();
		this.localImagePath = path;
		imageView.setImageBitmap(null);
		new VideoImageLoadTask(this).execute(path);
	}

	public void onLocalVideoImageLoaded(Bitmap bmp, String filePath) {
		showProgressView(false);
		hideLoader();
		if (localImagePath.equals(filePath))
			imageView.setImageBitmap(bmp);
	}

	class VideoImageLoadTask extends AsyncTask<String, Void, Bitmap> {

		private RemoteImageView mainContext;
		private String filePath;

		VideoImageLoadTask(RemoteImageView mainContext) {
			this.mainContext = mainContext;
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see android.os.AsyncTask#doInBackground(Params[])
		 */
		@Override
		protected Bitmap doInBackground(String... params) {
			this.filePath = params[0];
			Bitmap thumb = ThumbnailUtils.createVideoThumbnail(params[0],
					MediaStore.Images.Thumbnails.MICRO_KIND);
			return thumb;
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see android.os.AsyncTask#onPostExecute(java.lang.Object)
		 */
		@Override
		protected void onPostExecute(Bitmap result) {
			super.onPostExecute(result);
			mainContext.onLocalVideoImageLoaded(result, filePath);
		}

	}

	/**
	 * @param bitmap
	 */
	public void setImageBitMap(Bitmap bitmap) {
		imageView.setImageBitmap(bitmap);

	}

	public void setImageDrawable(Drawable drawable) {
		disableLoader();
		imageView.setImageDrawable(drawable);
		
	}

	public void setImageBitmap(Bitmap bitmap) {
		disableLoader();
		imageView.setImageBitmap(bitmap);
	}
}
